package com.inetools.gwt.gajaxs.client;

import com.google.gwt.core.client.JavaScriptObject;
import com.inetools.gwetons.client.RegExpJsni;

public class GCalenderDataApiInputOptions {
	protected String substantiate( String unverifiedStr, String exceptionMessage) 
	throws IllegalArgumentException 
	{
		if ( unverifiedStr == null) throw new IllegalArgumentException( exceptionMessage);
		String unverifiedStrCopy = unverifiedStr.trim();
		if ( unverifiedStrCopy.length() < 1) throw new IllegalArgumentException( exceptionMessage);
		return unverifiedStrCopy;
	}
	protected boolean isWhiteSpaceIn( String unverifiedStr, String exceptionMessage)
	throws IllegalArgumentException 
	{
		if ( unverifiedStr.contains( " ")) throw new IllegalArgumentException( exceptionMessage);
		return true;
	}
	
	// Google Calendar specific query parameters
	protected String userId = null;
	protected JavaScriptObject googleComRegExp = 
		RegExpJsni.getRegExp( "^\\S+@(gmail|google|group\\.calendar\\.google)\\.com$", true, false);
	public String getUserId() {
		return userId;
	}
	public void setUserId( String userId) throws IllegalArgumentException {
		String userIdCopy = 
			substantiate( userId, "Neither null nor empty string cannot be set to user ID.");
		isWhiteSpaceIn( userIdCopy, "As user ID value, \"" + userId + "\" should not contain white space.");
		if ( !RegExpJsni.test( googleComRegExp, userIdCopy)) {
			throw new IllegalArgumentException( 
					"As user ID, \"" + userIdCopy + "\" is not in the expected format as e-mail from " +
					"either gmail.com, group.calender.google.com or google.com");
		}
		this.userId = userIdCopy;
	}

	protected String visibility = GCalendarEventFeedParameterDefaultValue.VISIBILITY;
	public String getVisibility() {
		return visibility;
	}
	public void setVisibility( String visibility) throws IllegalArgumentException {
		String visibilityCopy = 
			substantiate( visibility, "Neither null nor empty string cannot be set to visibility.");
		isWhiteSpaceIn( 
				visibilityCopy, "As visibility value, \"" + visibility + "\" should not contain white space.");
		this.visibility = visibilityCopy;
	}

	protected String projection = GCalendarEventFeedParameterDefaultValue.PROJECTION;
	public String getProjection() {
		return projection;
	}
	public void setProjection( String projection) throws IllegalArgumentException {
		String projectionCopy = 
			substantiate( projection, "Neither null nor empty string cannot be set to projection.");
		isWhiteSpaceIn( 
				projectionCopy, "As projection value, \" + projection + \" should not contain white space.");
		this.projection = projectionCopy;
	}

	/**
	 * Could be null
	 */
	public String ctz = null;
	
	protected boolean futureEvents = GCalendarEventFeedParameterDefaultValue.FUTUREEVENTS;
	public boolean isFutureEvents() {
		return futureEvents;
	}
	public void setFutureEvents( boolean futureEvents) {
		this.futureEvents = futureEvents;
	}

	protected String orderBy = GCalendarEventFeedParameterDefaultValue.ORDERBY;
	public String getOrderBy() {
		return orderBy;
	}
	public void setOrderBy(String orderBy) throws IllegalArgumentException {
		String orderByCopy = 
			substantiate( orderBy, "Neither null nor empty string cannot be set to orderby.");
		isWhiteSpaceIn( orderByCopy, "As orderby value, \"" + orderBy + "\" should not contain white space.");
		this.orderBy = orderByCopy;
	}

	
	protected JavaScriptObject rfc3339TimeStampRegExp = 
		RegExpJsni.getRegExp( "^\\d{4}\\-\\d{2}\\-\\d{2}(T\\d{2}\\:\\d{2}\\:\\d{2}\\.\\d{3}(Z|(\\+|\\-)\\d{2}\\:\\d(2)))?$", true, false);
	
	protected String confirmRfc3339TimeStampFormat( String unverifiedStr, String notInFormatExceptionMessage) 
	throws IllegalArgumentException 
	{
		String unverifiedStrCopy;
		try {
			unverifiedStrCopy = substantiate( unverifiedStr, null);
		}
		catch( Exception exception) {
			return null;
		}
		if ( RegExpJsni.test( rfc3339TimeStampRegExp, unverifiedStrCopy)) {
			return unverifiedStrCopy;
		}
		else {
			throw new IllegalArgumentException( notInFormatExceptionMessage);
		}
	}
	
	/**
	 * Could be null
	 */
	protected String recurrenceExpansionStart = null;
	/**
	 * @return String formated in RFC 3339 time stamp or null
	 */
	public String getRecurrenceExpansionStart() {
		return recurrenceExpansionStart;
	}
	public void setRecurrenceExpansionStart( String recurrenceExpansionStart) 
	throws IllegalArgumentException 
	{
		this.recurrenceExpansionStart =  
			confirmRfc3339TimeStampFormat( 
					recurrenceExpansionStart, 
					"As recurrence-expansion-start value, \"" + 
					recurrenceExpansionStart + "\" needs to be in RFC 3339 time stamp format."
					);
	}

	/**
	 * Could be null
	 */
	public String recurrenceExpansionEnd = null;
	/**
	 * @return String formated in RFC 3339 time stamp or null
	 */
	public String getRecurrenceExpansionEnd() {
		return recurrenceExpansionEnd;
	}
	public void setRecurrenceExpansionEnd( String recurrenceExpansionEnd) throws IllegalArgumentException {
		this.recurrenceExpansionEnd = 
			confirmRfc3339TimeStampFormat( 
					recurrenceExpansionEnd, 
					"As recurrence-expansion-end value, \"" + 
					recurrenceExpansionEnd + "\" needs to be in RFC 3339 time stamp format."
					);
	}
	
	protected boolean singleEvents = GCalendarEventFeedParameterDefaultValue.SINGLEEVENTS;
	public boolean isSingleEvents() {
		return singleEvents;
	}
	public void setSingleEvents(boolean singleEvents) {
		this.singleEvents = singleEvents;
	}

	protected boolean showHidden = GCalendarEventFeedParameterDefaultValue.SHOWHIDDEN;
	public boolean isShowHidden() {
		return showHidden;
	}
	public void setShowHidden(boolean showHidden) {
		this.showHidden = showHidden;
	}

	protected String sortOrder = GCalendarEventFeedParameterDefaultValue.SORTORDER;
	public String getSortOrder() {
		return sortOrder;
	}
	public void setSortOrder(String sortOrder) throws IllegalArgumentException {
		String sortOrderCopy = 
			substantiate( sortOrder, "Neither null nor empty string cannot be set to sortorder.");
		isWhiteSpaceIn( 
				sortOrderCopy, "As sortorder value, \"" + sortOrder + "\" should not contain white space.");
		this.sortOrder = sortOrderCopy;
	}

	/**
	 * Could be null
	 */
	protected String startMin = null;
	/**
	 * @return String formated in RFC 3339 time stamp or null
	 */
	public String getStartMin() {
		return startMin;
	}
	public void setStartMin( String startMin) throws IllegalArgumentException {
		this.startMin = 
			confirmRfc3339TimeStampFormat( 
					startMin, 
					"As start-min value, \"" + startMin + "\" needs to be in RFC 3339 time stamp format."
					);
	}

	/**
	 * Could be null
	 */
	protected String startMax = null;
	/**
	 * @return String formated in RFC 3339 time stamp or null
	 */
	public String getStartMax() {
		return startMax;
	}
	public void setStartMax( String startMax) throws IllegalArgumentException {
		this.startMax = 
			confirmRfc3339TimeStampFormat( 
					startMax, 
					"As start-max value, \"" + startMax + "\" needs to be in RFC 3339 time stamp format."
					);
	}
	
	
	
	// Google data query parameters
	/**
	 * Could be null
	 */
	public String q = null;
	/**
	 * Could be null
	 */
	public String author = null;
	/**
	 * Could be null
	 */
	protected String updatedMin = null;
	/**
	 * @return String formated in RFC 3339 time stamp or null
	 */
	public String getUpdatedMin() {
		return updatedMin;
	}
	public void setUpdatedMin(String updatedMin) throws IllegalArgumentException {
		this.updatedMin = 
			confirmRfc3339TimeStampFormat( 
					updatedMin, 
					"As updatedMin value, \"" + updatedMin + "\" needs to be in RFC 3339 time stamp format."
					);
	}

	/**
	 * Could be null
	 */
	protected String updatedMax = null;
	/**
	 * @return String formated in RFC 3339 time stamp or null
	 */
	public String getUpdatedMax() {
		return updatedMax;
	}
	public void setUpdatedMax( String updatedMax) throws IllegalArgumentException {
		this.updatedMax = 
			confirmRfc3339TimeStampFormat( 
					updatedMax, 
					"As updatedMax value, \"" + updatedMax + "\" needs to be in RFC 3339 time stamp format."
					);
	}
	
	/**
	 * Could be null
	 */
	protected String publishedMin = null;
	/**
	 * @return String formated in RFC 3339 time stamp or null
	 */
	public String getPublishedMin() {
		return publishedMin;
	}
	public void setPublishedMin( String publishedMin) throws IllegalArgumentException {
		this.publishedMin = 
			confirmRfc3339TimeStampFormat( 
					publishedMin, 
					"As publishedMin value, \"" + 
					publishedMin + "\" needs to be in RFC 3339 time stamp format."
					);
	}

	/**
	 * Could be null
	 */
	protected String publishedMax = null;
	/**
	 * @return String formated in RFC 3339 time stamp or null
	 */
	public String getPublishedMax() {
		return publishedMax;
	}
	public void setPublishedMax( String publishedMax) throws IllegalArgumentException {
		this.publishedMax = 
			confirmRfc3339TimeStampFormat( 
					publishedMax, 
					"As publishedMax value, \"" + 
					publishedMax + "\" needs to be in RFC 3339 time stamp format."
					);
	}
	
	protected int startIndex = GCalendarEventFeedParameterDefaultValue.START_INDEX;
	public int getStartIndex() {
		return startIndex;
	}
	public void setStartIndex( int startIndex) throws IllegalArgumentException {
		if ( startIndex < GCalendarEventFeedParameterDefaultValue.START_INDEX) {
			throw new IllegalArgumentException( 
					startIndex + " is too small as startIndex value. It should be equal or bigger than " + 
					GCalendarEventFeedParameterDefaultValue.START_INDEX
					);
		}
		this.startIndex = startIndex;
	}

	protected int maxResults = GCalendarEventFeedParameterDefaultValue.MAX_RESULTS;
	public int getMaxResults() {
		return maxResults;
	}
	public void setMaxResults( int maxResults) throws IllegalArgumentException {
		if ( maxResults < 1) {
			throw new IllegalArgumentException( 
					maxResults + " is too small as maxResults value. It should be bigger than 0");
		}
		this.maxResults = maxResults;
	}
	
	/**
	 * Minimum required parameter is user ID
	 * @param userId
	 * @throws IllegalArgumentException
	 */
	public GCalenderDataApiInputOptions( String userId) throws IllegalArgumentException {
		setUserId( userId);
	}
	
	public GCalenderDataApiInputOptions( 
			GCalevenderLiteJsBridge.JsGCalenderDataApiInputOptions jsGCalenderDataApiInputOptions)
	throws IllegalArgumentException
	{
		// Google Calendar specific query parameters ----------------------------------------------
		setUserId( jsGCalenderDataApiInputOptions.getUserId());
		setVisibility( jsGCalenderDataApiInputOptions.getVisibility());
		setProjection( jsGCalenderDataApiInputOptions.getProjection());
		ctz = jsGCalenderDataApiInputOptions.getCtz();
		setFutureEvents( jsGCalenderDataApiInputOptions.getFutureEvents());
		setOrderBy( jsGCalenderDataApiInputOptions.getOrderBy());
		setRecurrenceExpansionStart( jsGCalenderDataApiInputOptions.getRecurrenceExpansionStart());
		setRecurrenceExpansionEnd( jsGCalenderDataApiInputOptions.getRecurrenceExpansionEnd());
		setSingleEvents( jsGCalenderDataApiInputOptions.getSingleEvents());
		setShowHidden( jsGCalenderDataApiInputOptions.getShowHidden());
		setSortOrder( jsGCalenderDataApiInputOptions.getSortOrder());
		setStartMin( jsGCalenderDataApiInputOptions.getStartMin());
		setStartMax( jsGCalenderDataApiInputOptions.getStartMax());
		// ----------------------------------------------------------------------------------------
		
		// Google data query parameters -----------------------------------------------------------
		q = jsGCalenderDataApiInputOptions.getQueryStr();
		author = jsGCalenderDataApiInputOptions.getAuthor();
		setUpdatedMin( jsGCalenderDataApiInputOptions.getUpdatedMin());
		setUpdatedMax( jsGCalenderDataApiInputOptions.getUpdatedMax());
		setPublishedMin( jsGCalenderDataApiInputOptions.getPublishedMin());
		setPublishedMax( jsGCalenderDataApiInputOptions.getPublishedMax());
		setStartIndex( jsGCalenderDataApiInputOptions.getStartIndex());
		setMaxResults( jsGCalenderDataApiInputOptions.getMaxResults());
		// ----------------------------------------------------------------------------------------
	}
}
